﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using HitachiLib.Data;

namespace HitachiApp.Model
{
    public class DragDropControl
    {
        private object drag_source;
        private object drop_target;
        public DataGrid src_control;
        public DataGrid dst_control;

        public object Source
        {
            get { return drag_source; }
            set { drag_source = value; }
        }

        public object Target
        {
            get { return drop_target; }
            set { drop_target = value; }
        }

        private static DragDropControl s_control;
        public static DragDropControl GetInstance()
        {
            if (s_control == null)
            {
                s_control = new DragDropControl();
            }
            return s_control;
        }

        public static void Clear()
        {
            DragDropControl ddc = GetInstance();
            ddc.Source = null;
            ddc.Target = null;
        }

        private DragDropControl()
        {
        }

        public void ProcessDDC()
        {
            if (drag_source == drop_target || drag_source == null || drop_target == null)
            {
                Clear();
                return;
            }
            if (drag_source is ProjectListViewModel)
            {
                ProjectListViewModel src_pm = drag_source as ProjectListViewModel;
                if (drop_target is ProjectListViewModel)
                {
                    // ignore
                }
                else if (drop_target is ScheduleUnitTimeControlModel)
                {
                    ScheduleUnitTimeControlModel dst_sm = drop_target as ScheduleUnitTimeControlModel;
                    if (dst_sm.Common)
                    {
                        AddCommonSchedule(src_pm, dst_sm);
                    }
                    else
                    {
                        // ignore
                    }
                }
            }
            else if (drag_source is ScheduleUnitTimeControlModel)
            {
                ScheduleUnitTimeControlModel src_sm = drag_source as ScheduleUnitTimeControlModel;
                if (src_sm.Common)
                {
                    if (drop_target is ProjectListViewModel)
                    {
                        ProjectListViewModel dst_pm = drop_target as ProjectListViewModel;
                        RemoveCommonSchedule(src_sm, dst_pm);
                    }
                    else if (drop_target is ScheduleUnitTimeControlModel)
                    {
                        ScheduleUnitTimeControlModel dst_sm = drop_target as ScheduleUnitTimeControlModel;
                        if (dst_sm.Common)
                        {
                            EditSchedule(src_sm, dst_sm);
                        }
                        else
                        {
                            AddYearlySchedule(src_sm, dst_sm);
                        }
                    }
                }
                else
                {
                    if (drop_target is ProjectListViewModel)
                    {
                        // ignore
                    }
                    else if (drop_target is ScheduleUnitTimeControlModel)
                    {
                        ScheduleUnitTimeControlModel dst_sm = drop_target as ScheduleUnitTimeControlModel;
                        if (dst_sm.Common)
                        {
                            RemoveYearlySchedule(src_sm);
                        }
                        else
                        {
                            EditSchedule(src_sm, dst_sm);
                        }
                    }
                }
            }
            Clear();
        }

        private IList<ViewItem> GetSelected(IList<ViewItem> list)
        {
            List<ViewItem> r = new List<ViewItem>();
            foreach (ViewItem vi in list)
            {
                if (vi.Selected)
                {
                    r.Add(vi);
                }
            }
            return r;
        }

        private IList<ViewItem> Clone(IList<ViewItem> list, bool c)
        {
            List<ViewItem> r = new List<ViewItem>();
            foreach (ViewItem vi in list)
            {
                ViewItem cloned = new ViewItem(vi.Project, c);
                r.Add(cloned);
            }
            return r;
        }

        private IList<ViewItem> Clone(IList<ViewItem> list)
        {
            List<ViewItem> r = new List<ViewItem>();
            foreach (ViewItem vi in list)
            {
                ViewItem cloned = new ViewItem(vi.Project, vi.Common);
                r.Add(cloned);
            }
            return r;
        }

        private void Add(IList<ViewItem> list, IList<ViewItem> change)
        {
            foreach (ViewItem vi in change)
            {
                list.Add(vi);
            }
        }

        private void Remove(IList<ViewItem> list, IList<ViewItem> change)
        {
            foreach (ViewItem vi in change)
            {
                list.Remove(vi);
            }
        }

        private void Rebind()
        {
            System.Collections.IEnumerable tmp;
            tmp = src_control.ItemsSource;
            src_control.ItemsSource = null;
            src_control.ItemsSource = tmp;
            src_control.UpdateLayout();
            tmp = dst_control.ItemsSource;
            dst_control.ItemsSource = null;
            dst_control.ItemsSource = tmp;
            dst_control.UpdateLayout();
        }

        private void AddCommonSchedule(ProjectListViewModel src_pm, ScheduleUnitTimeControlModel dst_sm)
        {
            ObservableCollection<ViewItem> src_vi = src_pm.ProjectList;
            ObservableCollection<ViewItem> dst_vi = dst_sm.UnitTimeProjects;
            IList<ViewItem> rm_list = GetSelected(src_vi);
            IList<ViewItem> add_list = Clone(rm_list, true);
            foreach (ViewItem vi in add_list)
            {
                dst_sm.ApplyToProject(vi);
            }
            Remove(src_vi, rm_list);
            Add(dst_vi, add_list);
            Rebind();
        }

        private void AddYearlySchedule(ScheduleUnitTimeControlModel src_sm, ScheduleUnitTimeControlModel dst_sm)
        {
            ObservableCollection<ViewItem> src_vi = src_sm.UnitTimeProjects;
            ObservableCollection<ViewItem> dst_vi = dst_sm.UnitTimeProjects;
            IList<ViewItem> rm_list = GetSelected(src_vi);
            IList<ViewItem> add_list = Clone(rm_list, false);
            foreach (ViewItem vi in rm_list)
            {
                vi.Selected = false;
            }
            foreach (ViewItem vi in add_list)
            {
                dst_sm.ApplyToProject(vi);
            }
            Add(dst_vi, add_list);
            Rebind();
        }

        private void RemoveYearlySchedule(ScheduleUnitTimeControlModel src_sm)
        {
            ObservableCollection<ViewItem> src_vi = src_sm.UnitTimeProjects;
            IList<ViewItem> rm_list = GetSelected(src_vi);
            foreach (ViewItem vi in rm_list)
            {
                src_sm.RemoveProject(vi);
            }
            Remove(src_vi, rm_list);
            Rebind();
        }

        private void RemoveCommonSchedule(ScheduleUnitTimeControlModel src_sm, ProjectListViewModel dst_pm)
        {
            ObservableCollection<ViewItem> src_vi = src_sm.UnitTimeProjects;
            ObservableCollection<ViewItem> dst_vi = dst_pm.ProjectList;
            IList<ViewItem> rm_list = GetSelected(src_vi);
            IList<ViewItem> add_list = Clone(rm_list, true);
            foreach (ViewItem vi in add_list)
            {
                dst_pm.ApplyToProject(vi);
            }
            Remove(src_vi, rm_list);
            Add(dst_vi, add_list);
            Rebind();
        }

        private void EditSchedule(ScheduleUnitTimeControlModel src_sm, ScheduleUnitTimeControlModel dst_sm)
        {
            ObservableCollection<ViewItem> src_vi = src_sm.UnitTimeProjects;
            ObservableCollection<ViewItem> dst_vi = dst_sm.UnitTimeProjects;
            IList<ViewItem> rm_list = GetSelected(src_vi);
            IList<ViewItem> add_list = Clone(rm_list);
            foreach (ViewItem vi in add_list)
            {
                dst_sm.ApplyToProject(vi);
            }
            Remove(src_vi, rm_list);
            Add(dst_vi, add_list);
            Rebind();
        }
    }
}
